package main

import (
	"github.com/BurntSushi/toml"
	"github.com/garyburd/redigo/redis"
	"github.com/kataras/iris"
	"github.com/ngaut/log"
	"server/ote/model"
	"time"
	"sync"
)

var ote *Context
var OFFICIAL_UID = 0

// 上下文
type Context struct {

	startTime 		time.Time

	// 配置
	Configuration

	mu 	sync.Mutex

	// Redis 映射表
	RedisPool map[string]*redis.Pool

	// 数据
	*Data

	workers map[string]*Worker

	depths map[string]*Depth
}

func New() *Context {
	return &Context{
		RedisPool: 	make(map[string]*redis.Pool),
		Data:      	NewData(),
		workers: 	make(map[string]*Worker),
		depths: 	make(map[string]*Depth),
	}
}

// 检查交易对是否是工作状态
func (c *Context) CheckCoinPiarWorking(coinPair string) bool {
	if _, ok := c.workers[coinPair]; ok {
		return true
	}
	return false
}

func (c *Context) setCoinfigure(configuration Configuration) {
	c.Configuration = configuration
}

func (c *Context) RegistWorker(key string, worker *Worker) {
	c.mu.Lock()
	c.workers[key] = worker
	c.mu.Unlock()
}

func (c *Context) RegistDepth(key string, depth *Depth) {
	c.mu.Lock()
	c.depths[key] = depth
	c.mu.Unlock()
}

func (c *Context) RemoveDepth(key string)  {
	if _, ok := c.depths[key]; ok {
		c.mu.Lock()
		delete(c.depths, key)
		c.mu.Unlock()
	}
}

// 初始化
func (c *Context) bootstrap() *Context {
	// config
	c.setCoinfigure(loadConfiguration())

	// log
	c.Log.Setting()

	// redis
	c.registRedis()

	// db
	c.db()

	return c
}

func (c *Context) initialize() {
	c.startTime = time.Now()
	c.Data.LoadData()
	if len(c.Data.CoinPair) == 0 {
		panic("init coin pair data error")
	}
	if c.Configuration.App.OfficialUid == 0 {
		OFFICIAL_UID = model.DEFAULT_OFFICIAL_UID
	} else {
		OFFICIAL_UID = c.Configuration.App.OfficialUid
	}
}

func (c *Context) serv() {
	m := NewManager(c)
	m.Serv()
}

func (c *Context) db() {
	if conf, ok := c.Db["main"]; ok {
		logOn, file := conf.GetDBLogConfig()
		model.InitMainDB(conf.FormatDBConnection(), logOn, file)
		log.Infof("main database configuration ok.")
	} else {
		log.Errorf("check main database config.")
	}
}

func (c *Context) registRedis() {
	for key, conf := range c.Redis {
		pool := conf.redisPool()
		if pool == nil {
			panic("redis init error")
		}
		c.RedisPool[key] = conf.redisPool()
	}

	if len(c.RedisPool) == 0 {
		panic("redis init error, please check config.")
	}
}

func (c *Context) GetOteRedis() *redis.Pool {
	p, ok := c.RedisPool["ote"]
	if !ok {
		panic("get redis pool of ote failed")
	}
	return p
}

func server() {

	defer func() {
		if err := recover(); err != nil {
			log.Errorf("ote server start failed.")
		}
	}()

	c := New()
	c.bootstrap().initialize()
	c.serv()

	ote = c

	log.Infof("official uid: %d", OFFICIAL_UID)

	app := iris.New()
	registApiRoutes(app)
	app.Run(iris.Addr(c.Http.GetAddr()))
}

func loadConfiguration() Configuration {
	configuration := newConfiguration()
	_, err := toml.DecodeFile(CONFIG_FILE, &configuration)
	if err != nil {
		panic(err.Error())
	}
	return configuration
}
